﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using AltimilliaLibrary.Base_Object;
using Microsoft.Xna.Framework.Graphics;
using AltimilliaLibrary.State;

namespace AltimilliaLibrary
{
  public abstract class Sprite : IAltimilliaGameComponent
  {
    public enum Facing
    {
      Back, Left, Right, Forward, None
    }

    #region Properties
    public Vector2 absPosition { get; set; }
    protected Point tilePosition;
    public Point TilePosition
    {
      get
      {
        return tilePosition;
      }
      set
      {
        tilePosition = value;
      }
    }
    public bool Scrolling { get; set; }
    public bool Enabled { get; set; }
    public float maxSpeed { get; set; }
    public Facing SpriteFacing { get; set; }
    public int UpdateOrder { get; set; }
    public int DrawOrder { get; set; }
    public bool Visible { get; set; }
    public AnimationData AnimData { get; set; }
    private Animation Animation;
    public IState State { get; set; }
    public GameTime gameTime { get; set; }

    #endregion

    #region Event

    public event EventHandler EnabledChanged;
    public event EventHandler DrawOrderChanged;
    public event EventHandler UpdateOrderChanged;
    public event EventHandler VisibleChanged;

    #endregion

    public Sprite(Point TilePosition, Facing SpriteFacing, float maxSpeed, AnimationData AnimationData)
    {
      this.tilePosition = TilePosition;
      this.SpriteFacing = SpriteFacing;
      this.maxSpeed = maxSpeed;
      this.absPosition = Utilities.ConvertTileToAbsPosition(tilePosition);
      this.AnimData = AnimationData;
      Animation = new Animation(AnimData, 10);
      gameTime = new GameTime();
    }

    public virtual void Initialize()
    {
    }
    public virtual void Update(GameTime gameTime)
    {
      this.gameTime = gameTime;
      Animation.UpdateFrame((float)gameTime.ElapsedGameTime.TotalSeconds);
    }
    public virtual void Draw(GameTime gameTime)
    {
      this.spriteManager.batch.Begin();
      this.spriteManager.batch.Draw(this.Animation.AnimData.Texture, this.absPosition, this.Animation.CurrentFrame.Rectangle,
        Color.White, this.Animation.CurrentFrame.Rotation, new Vector2(0),1 ,this.Animation.CurrentFrame.SpriteEffects, 0);
      this.spriteManager.batch.End();
    }

    public BaseManager Manager { get; set; }
    public SpriteManager spriteManager
    {
      get
      {
        return (SpriteManager)Manager;
      }
    }

    public void MoveDirection(WalkDirection direction)
    {
      bool condition = false;
      bool isUpDown = false;
      int amount = 0;
      switch (direction)
      {
        case WalkDirection.WalkLeft:
          isUpDown = false;
          amount = -1;
          condition = (this.absPosition.X > Utilities.TiletoPixel(TilePosition.X - 1));
          break;
        case WalkDirection.WalkRight:
          isUpDown = false;
          amount = 1;
          condition = (this.absPosition.X < Utilities.TiletoPixel(TilePosition.X + 1));
          break;
        case WalkDirection.WalkUp:
          amount = -1;
          condition = (this.absPosition.Y > Utilities.TiletoPixel(TilePosition.Y - 1));
          isUpDown = true;
          break;
        case WalkDirection.WalkDown:
          amount = 1;
          isUpDown = true;
          condition = (this.absPosition.Y < Utilities.TiletoPixel(TilePosition.Y + 1));
          break;
      }


      if (this.Scrolling)
      {
        if (condition)
        {
          this.State.UpdatePosition(this);
        }
        else
        {
          if (isUpDown)
          {
            tilePosition.Y += amount;
          }
          else
          {
            tilePosition.X += amount;
          }
          Scrolling = false;
        }
      }
      else
      {
        this.State.UpdatePosition(this);
      }
    }

    public void ChangeDirection(WalkDirection newDirection)
    {
      if (newDirection.ToString() == this.State.GetState())
      {
        return;
      }
      switch (newDirection.ToString())
      {
        case "WalkLeft":
          State = WalkLeft.GetInstance();
          this.Animation.CurrentBehaviour = "WalkLeft";
          break;
        case "WalkRight":
          State = WalkRight.GetInstance();
          this.Animation.CurrentBehaviour = "WalkRight";
          break;
        case "WalkDown":
          State = WalkDown.GetInstance();
          this.Animation.CurrentBehaviour = "WalkDown";
          break;
        case "WalkUp":
          State = WalkUp.GetInstance();
          this.Animation.CurrentBehaviour = "WalkUp";
          break;
      }
    }
  }
}
